home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
fortran.zip
/
WASM.ZIP
/
SOUND.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-08-13
|
17KB
|
693 lines
Title 'Wolfware Assembler Sample Program', 'Sound Generation'
;=============================================================================
; Sound Generation
;
; This program allows you to enter frequencies, a rate of change (velocity),
; a rate of rate of change (acceleration), and a duration for any number
; (memory allowing) of speaker beeps. The beeps can be added, modified, and
; played back all together to form a sort of music. The sequence of beeps
; can also be saved to or read from a file (loading and playing a file at
; random has an interesting effect). The frequency is in hertz, the velocity
; is in hertz per 1/50 seconds, the acceleration is in hertz per 1/50
; seconds^2, and the duration is in 1/100 seconds.
;
; The IO.BIN runtime library is needed on the default drive/path for
; execution, and the files IO.MAC, IO.RED, and DISPATCH.ASM are all needed for
; assembly. Also ANSI.SYS or a compatible device driver must be installed.
;
; This program is completely DOS compatible execept for the sound generation,
; which is hardware dependent. Note that all those mysterious characters
; stuck in the middle of strings are ANSI escape sequences which the ANSI.SYS
; device driver uses to control the screen attributes, cursor position, etc.
;
; The timing of this program is based on a 4.77 MHz 8088 microprocessor (see
; IO.ASM). If a faster computer is used, the timing will probably be off.
Jmp Begin
;================================================
; Data
;--- present sound data
Snd_Idx Dw 1 ;present sound number
Snd_Now Dw 523 ;frequency
Snd_Vel Dw 1 ;velocity
Snd_Acc Dw 10 ;acceleration
Snd_Dur Dw 10 ;duration
Dwn_Snd Equ 01h ;tone goes down instead of up
Snd_Sta Dw 0 ;tone status
;--- tone limits
Ton_Max Dw 2000 ;maximum tone
Ton_Min Dw 100 ;minimum tone
Dur_Max Dw 500 ;maximum duration, 5 seconds
;--- tones defined
Snd_Num Dw 0 ;number of tones defined
Snd_End Dw 0 ;end of tone sequence
Snd_Seg Dw ? ;segment of tone sequence
Snd_Siz Dw ? ;end of tone segment
;--- other
Err_Ton Equ 500 ;error beep frequency
Err_Dur Equ 5 ;error beep duration
Nam_Siz Equ 60 ;file name size
Stack_Size Equ 100 ;bytes for stack
;--- external source files
Include 'Io.Mac'
Include 'Io.Red'
Include 'Dispatch.Asm'
;------------------------------------------------
; Execute a DOS function call.
Dos Macro Func
Mov Ah, Func ;load function
Int 21h ;execute
Endm ;Dos
;================================================
; Main program.
Begin
;--- initialization, set stack
Mov Sp, Offset Stack_Top ;switch to local stack
;--- reduce present memory
Mov Bx, Offset End ;end of program
Mov Cl, 4 ;bits to shift
Shr Bx, Cl ;make paragraph form
Inc Bx
Dos 4ah ;reduce memory allocation
;--- allocate sequence space
Mov Bx, 0fffh ;try to allocate nearly whole segment
Dos 48h ;allocate
Jnc Bigsong ;jump if ok
Dos 48h ;allocate what's available
Jc Memerror ;jump if still error
Bigsong
Mov Snd_Seg, Ax ;save segment
Mov Cl, 4 ;bits to shift
Shl Bx, Cl ;make byte form
Mov Ax, Bx
Mov Bx, 10
Sub Dx, DX
Div Ax, Bx ;divide by ten
Mul Ax, Bx ;multiply by ten
Mov Snd_Siz, Ax ;save end pointer (a multiple of ten)
;--- set the screen
Normal ;set to normal attribute
Cls ;clear screen
Jmps Maincont ;jump if so
;--- memory error
Memerror
Line 'SOUND: Memory error' ;display error message
Dos 4ch ;exit
;--- main program
Maincont
Display Mainmess1 ;show main menu
Decimal Snd_Num ;make tone number a string
Locate 4, 20 ;goto position
Bold ;attribute
Display ;show it
Normal ;fix attribute
Locate 14, 1 ;goto position
Mov Si, Offset Mainmess3 ;choice message
Call Input_Chr ;input character
Cmp Al, 'A' ;check if A
Je Main1
Cmp Al, 'M' ;check if M
Je Main2
Cmp Al, 'P' ;check if P
Je Main3
Cmp Al, 'S' ;check if S
Je Main4
Cmp Al, 'L' ;check if L
Je Main5
Cmp Al, 'C' ;check if C
Je Main6
Cmp Al, 'Q' ;check if Q
Je Main7
Sound Err_Ton, Err_Dur ;error beep
Jmps Maincont
;--- add new sound
Main1
Call Add_Sound ;add new sound
Jmp Maincont
;--- modify old sound
Main2
Call Mod_Sound ;modify sound
Jmp Maincont
;--- play all sounds
Main3
Call Play_Sounds ;play all sounds
Jmp Maincont
;--- save to file
Main4
Call Write_Sounds ;write sounds to file
Jmp Maincont
;--- load from file
Main5
Call Read_Sounds ;read sounds from file
Jmp Maincont
;--- clear all sounds
Main6
Call Clear_Sounds ;clear all sounds
Jmp Maincont
;--- exit program
Main7
Dos 4ch ;exit
;--- data
Mainmess1 Label Byte
Db Byte (Offset Mainmess2 - Offset Mainmess1 -1)
Db 27,'[2J'
Db 13,10
Db 'Sound Generator Version 1.00',13,10
Db 13,10
Db ' Defined sounds = ',13,10
Db 13,10
Db ' (',27,'[1mA',27,'[0m)dd a new sound',13,10
Db ' (',27,'[1mM',27,'[0m)odify an old sound',13,10
Db ' (',27,'[1mP',27,'[0m)lay all sounds',13,10
Db ' (',27,'[1mS',27,'[0m)ave to file',13,10
Db ' (',27,'[1mL',27,'[0m)oad from file',13,10
Db ' (',27,'[1mC',27,'[0m)lear all sounds',13,10
Db ' (',27,'[1mQ',27,'[0m)uit',13,10
Mainmess2
Mainmess3 Db 14,'Enter choice: '
;================================================
; Add new sound to sequence.
Add_Sound Proc Near
Mov Ax, Snd_End ;end of sounds
Cmp Ax, Snd_Siz ;check if full
Je Addsonerr ;jump if so
Inc Snd_Num ;increment number of sounds
Display Addsonmess1 ;show message
Decimal Snd_Num ;make string
Bold ;set to bold
Display ;show number
Normal
Line
Line ;skip a line
Mov Si, Snd_End ;sound pointer
Call Set_Sound ;set sound
Add Snd_End, 10 ;advance pointer
Ret
;--- too many sounds
Addsonerr
Display Addsonmess2 ;show error message
Sound Err_Ton, Err_Dur ;error beep
Call Wait ;wait for key
Ret
;--- messages
Addsonmess1 Db 15,13,10,'Adding sound '
Addsonmess2 Db 15,'Too many sounds'
Endp ;Add_Sound
;================================================
; Modify an old sound.
Mod_Sound Proc Near
Mov Si, Offset Modsonmess ;message
Mov Di, Offset Snd_Idx ;present sound
Call Input_Num ;input number
Dec Ax ;adjust to scale starting at zero
Cmp Ax, Snd_Num ;check if past end
Jae Modsonadd ;jump if so, add instead
;--- modify old sound
Line
Mov Bx, 10
Mul Ax, Bx ;get offset into sequence
Mov Si, Ax
Push Ds
Mov Ds, Snd_Seg ;set tone segment
Mov Ax, [Si] ;starting tone
Cs:
Mov Snd_Now, Ax ;save
Mov Bx, [Si+2] ;tone velocity
Cs:
Mov Snd_Vel, Bx ;save
Mov Dx, [Si+4] ;tone acceleration
Cs:
Mov Snd_Acc, Dx ;save
Mov Cx, [Si+6] ;tone duration
Cs:
Mov Snd_Dur, Cx ;save
Mov Bp, [Si+8] ;tone status
Cs:
Mov Snd_Sta, Bp ;save
Pop Ds
Call Set_Sound ;set sound
Ret
;--- add new sound
Modsonadd
Call Add_Sound ;add new sound
Ret
;--- messages
Modsonmess Label Byte
Db 38
Db 13,10
Db 'Modifying old sound',13,10
Db 13,10
Db 'Enter index ['
Endp ;Mod_Sound
;================================================
; Play all sounds.
Play_Sounds Proc Near
Display Playmess ;show message
Sub Si, Si ;start of segment
;--- loop until end of tones is reached
Playloop
Cmp Si, Snd_End ;check if done
Je Playdone ;jump if so
Keyboard ;check if key
Jnz Playstop ;jump if so
Push Ds
Mov Ds, Snd_Seg ;set tone segment
Mov Ax, [Si] ;starting tone
Mov Bx, [Si+2] ;tone velocity
Mov Dx, [Si+4] ;tone acceleration
Mov Cx, [Si+6] ;tone duration
Mov Bp, [Si+8] ;tone status
Pop Ds
Push Si
Test Bp, Dwn_Snd ;test if down
Jnz Playtondn ;jump if so
;--- tone goes up
Call Tone_Up ;sound tone up
Pop Si
Add Si, 10 ;next entry
Jmps Playloop
;--- tone goes down
Playtondn
Call Tone_Dn ;sound tone down
Pop Si
Add Si, 10 ;next entry
Jmps Playloop
;--- playing stopped or finished
Playstop
Input ;throw away key
Playdone
Ret
;--- message
Playmess Db 20,13,10, 'Playing all sounds'
Endp ;Play_Sounds
;================================================
; Write sounds to a file.
Write_Sounds Proc Near
Display Writesmess1 ;display
Input Nam_Siz ;input file name
Create ;create file
Jc Writeserr ;jump if error
Write , Snd_End, 0, Snd_Seg ;write to file
Add Sp, 2 ;throw away bytes written
Close ;close it
Ret
;--- error creating file
Writeserr
Add Sp, 2 ;throw away handle
Display Writesmess2 ;display error message
Sound Err_Ton, Err_Dur ;error beep
Call Wait ;wait for key
Ret
;--- data
Writesmess1 Label Byte
Db 45
Db 13,10
Db 'Writing sounds to file',13,10
Db 13,10
Db 'Enter file name: '
Writesmess2 Label Byte
Db 23,13,10,'Could not create file'
Endp ;Write_Sounds
;================================================
; Load sounds from a file.
Read_Sounds Proc Near
Display Readsmess1 ;display
Input Nam_Siz ;input file name
Open ;open file
Jc Readserr ;jump if error
Read , Snd_Siz, 0, Snd_Seg ;read from file
Pop Ax ;bytes read
Mov Bx, 10
Sub Dx, DX
Div Ax, Bx ;divide by ten
Mov Snd_Num, Ax ;save number of sounds
Mul Ax, Bx ;multiply by ten
Mov Snd_End, Ax ;make it an even ten multiple
Mov Snd_Idx, 1 ;reset last index
Close ;close file
Ret
;--- error opening file
Readserr
Add Sp, 2 ;throw away handle
Display Readsmess2 ;display error message
Sound Err_Ton, Err_Dur ;error beep
Call Wait ;wait for key
Ret
;--- data
Readsmess1 Label Byte
Db 47
Db 13,10
Db 'Reading sounds from file',13,10
Db 13,10
Db 'Enter file name: '
Readsmess2 Label Byte
Db 21,13,10,'Could not open file'
Endp ;Read_Sounds
;================================================
; Clear all sounds.
Clear_Sounds Proc Near
Mov Snd_Num, 0 ;set number defined to zero
Mov Snd_End, 0 ;set pointer to start
Mov Snd_Idx, 1 ;set index to first
Ret
Endp ;Clear_Sounds
;================================================
; Set all sound characteristics. The sound is
; set to the seqence location at SI.
Set_Sound Proc Near
Push Si
;--- set frequency
Mov Si, Offset Tonmess1 ;message
Mov Di, Offset Snd_Now ;number
Call Input_Num ;input number
;--- set velocity
Mov Si, Offset Tonmess2 ;message
Mov Di, Offset Snd_Vel ;number
Call Input_Num ;input number
;--- set acceleration
Mov Si, Offset Tonmess3 ;message
Mov Di, Offset Snd_Acc ;number
Call Input_Num ;input number
;--- set duration
Mov Si, Offset Tonmess4 ;message
Mov Di, Offset Snd_Dur ;number
Call Input_Num ;input number
;--- set up or down
Tonudrep
Mov Si, Offset Tonmess5 ;message
Call Input_Chr ;input
Cmp Al, 'U' ;check if U
Je Tonup
Cmp Al, 'D' ;check if D
Je Tondn
Sound Err_Ton, Err_Dur ;error beep
Jmps Tonudrep ;loop back if error
Tonup
And Snd_Sta, Not Dwn_Snd ;clear down bit
Jmps Toncont
Tondn
Or Snd_Sta, Dwn_Snd ;set down bit
;--- play tone
Toncont
Pop Si
Push Ds
Mov Ds, Snd_Seg ;set tone segment
Cs:
Mov Ax, Snd_Now ;starting tone
Mov [Si], Ax ;save
Cs:
Mov Bx, Snd_Vel ;tone velocity
Mov [Si+2], Bx ;save
Cs:
Mov Dx, Snd_Acc ;tone acceleration
Mov [Si+4], Dx ;save
Cs:
Mov Cx, Snd_Dur ;tone duration
Mov [Si+6], Cx ;save
Cs:
Mov Bp, Snd_Sta ;tone status
Mov [Si+8], Bp ;save
Pop Ds
Test Bp, Dwn_Snd ;test if down
Jnz Gotondn ;jump if so
Call Tone_Up ;sound tone up
Ret
Gotondn
Call Tone_Dn ;sound tone down
Ret
;--- data
Tonmess1 Db 12,'Enter tone ['
Tonmess2 Db 16,'Enter velocity ['
Tonmess3 Db 20,'Enter acceleration ['
Tonmess4 Db 16,'Enter duration ['
Tonmess5 Db 38,'Enter (',27,'[1mU',27,'[0m)p or (',27,'[1mD',27,'[0m)own: '
Endp
;================================================
; Sound the speaker up. The the starting tone
; must be in AX, velocity in BX, the acceleration
; in DX, and the duration in CX.
Tone_Up Proc Near
Mov Di, Ton_Max ;maximum tone
Cmp Cx, Dur_Max ;check if too long
Jne Tonudok ;jump if ok
Mov Cx, Dur_Max ;set to max
Tonudok
Shr Cx ;cut duration in half
Inc Cx ;add one
Tonuploop
Sound Ax, 2 ;sound speaker
Add Ax, Bx ;increase frequency
Jc Tonupdone ;jump if overflow
Cmp Ax, Di ;check high range
Ja Tonupdone
Add Bx, Dx ;increase velocity
Loop Tonuploop ;loop back if more
Tonupdone Ret
Endp ;Tone_Up
;================================================
; Sound the speaker down. The the starting tone
; must be in AX, velocity in BX, the acceleration
; in DX, and the duration in CX.
Tone_Dn Proc Near
Mov Di, Ton_Min ;minimum tone
Cmp Cx, Dur_Max ;check if too long
Jne Tonddok ;jump if ok
Mov Cx, Dur_Max ;set to max
Tonddok
Shr Cx ;cut in duration in half
Inc Cx ;add one
Tondnloop
Sound Ax, 2 ;sound speaker
Sub Ax, Bx ;decrease frequency
Jc Tondndone ;jump if underflow
Cmp Ax, Di ;check lower range
Jb Tondndone ;jump if out of range
Add Bx, Dx ;increase velocity
Loop Tondnloop ;loop back if more
Tondndone Ret
Endp ;Tone_Dn
;================================================
; Display the string at SI and input a single
; character. The character is converted to
; upper-case.
Input_Chr Proc Near
Display Si ;display string
Input ;input character to AL
Line Al ;echo
Uppercase ;convert to upper-case
Ret
Endp ;Input_Chr
;================================================
; Display the string at SI and input a number.
; The storage for the number should be at DI. The
; number is set to [DI] and returned in AX.
Input_Num Proc Near
Inputerrlo
Display Si ;display string
Decimal Word [Di] ;convert to string
Bold ;set to bold
Display ;show it
Normal ;set to normal
Display Inpfinish ;display end part
Input 5 ;input number
Jz Inputndef ;jump if default
Binary ;convert to binary
Jc Inputnerr ;jump if error
Pop Dx
Pop Ax ;get number in DX:AX
Or Dx, Dx ;check if really 16 bit
Jnz Input_Num ;jump back and try again if not
Mov [Di], Ax ;save value
Ret
;--- use default number
Inputndef
Add Sp, 4 ;throw away input string location
Mov Ax, [Di] ;get number
Ret
;--- error in number
Inputnerr
Add Sp, 4 ;throw away number returned, no good
Sound Err_Ton, Err_Dur ;error beep
Jmps Inputerrlo ;try again
;--- data
Inpfinish Db 3, ']: '
Endp ;Input_Num
;================================================
; Display prompt and wait for any key.
Wait Proc Near
Line
Line
Display '[press any key]' ;show message
Input ;wait for key
Ret
Endp ;Wait
;================================================
; Stack.
Org +Stack_Size
Stack_Top Label Byte
End